﻿/*                              
   Copyright 2011 Nils Kopal, Christopher Krüger, Simone Sauer, Dennis Nolte, Uni Duisburg-Essen

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
using System;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Sharebert.PeerLibrary;
using System.Net;

namespace SharebertPeerLibraryDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private DownloadListener _listener;
        private DownloadClient _client;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Download_Click(object sender, RoutedEventArgs e)
        {
            Download.IsEnabled = false;
            IPAddress iPAddress;
            int remotePort;
            string file;
            try
            {
                iPAddress = IPAddress.Parse(IP.Text);
                remotePort = Int32.Parse(Port.Text);
                file = File.Text;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can not start the Download: " + ex.Message, "Error", MessageBoxButton.OK);
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
                {
                    Download.IsEnabled = true;
                }
                , null);
                return;
            }

            new Thread(delegate(){
            try
            {                
                _client = new DownloadClient(iPAddress, remotePort);
                _client.ErrorOccurred += new EventHandler<ErrorArgs>(_client_ErrorOccured);
                _client.DownloadStatusChanged += new EventHandler<DownloadStatusEventArgs>(_client_DownloadStatusChanged);
                _client.FileCompleted += new EventHandler<FileCompletedEventArgs>(_client_FileCompleted);
                _client.FileNotFound += new EventHandler<FileNotFoundEventArgs>(_client_FileNotFound);
                _client.TimedOut +=new EventHandler<EventArgs>(_client_TimedOut);
                //_client.RequestFile(file, 0); has to be repaired...
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can not start the Download: " + ex.Message, "Error", MessageBoxButton.OK);
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
                {
                    Download.IsEnabled = true;
                }
                , null);
            }
            }) { Name = "DownloadThread" }.Start();
        }

        private void _client_TimedOut(object sender, EventArgs e)
        {
            MessageBox.Show("Timeout occured", "TimedOut", MessageBoxButton.OK);
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
            {
                Download.IsEnabled = true;
            }
               , null);
        }

        private void _client_FileNotFound(object sender, FileNotFoundEventArgs e)
        {
            MessageBox.Show("The file " + e.Filename + " was not found.", "File not found", MessageBoxButton.OK);
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
            {
                Download.IsEnabled = true;
            }
            , null);
        }

        private void _client_FileCompleted(object sender, FileCompletedEventArgs e)
        {
            try
            {
                var stream = System.IO.File.OpenWrite("files\\" + e.Filename);
                //stream.Write(e.Filebytes, 0, e.Filebytes.Length);
                stream.Flush();
                stream.Close();
                MessageBox.Show("File " + e.Filename + " successfully downloaded.", "Downloaded", MessageBoxButton.OK);
            }
            catch(Exception ex)
            {
                MessageBox.Show("Error processing the downloaded file: " + ex.Message, "Error", MessageBoxButton.OK);                
            }
            finally
            {
                Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
                {
                    Download.IsEnabled = true;
                }
                , null);
            }
        }

        private void _client_DownloadStatusChanged(object sender, DownloadStatusEventArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
            {
                DownloadBar.Value = e.PercentageFinished * 100;
                DownloadBarText.Text = string.Format("{0} at {1:0.00} kb/sec", e.Filename, (double)e.BytesPerSecond / 1024);
            }
            , null);
        }

        private void _client_ErrorOccured(object sender, ErrorArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
            {
                Download.IsEnabled = false;
            }
            , null);
            
            MessageBox.Show("Error occured: " + e.Exception.Message, "Error", MessageBoxButton.OK);
            Environment.Exit(-1);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if(_listener == null)
            {
                try
                {
                    _listener = new DownloadListener(IPAddress.Any, 1234);
                    _listener.DownloadersChanged +=new EventHandler<DownloadersArgs>(_listener_DownloadersChanged);
                    _listener.ErrorOccured +=new EventHandler<ErrorArgs>(_listener_ErrorOccured);
                    _listener.FileRequestReceived+=new EventHandler<FileRequestEventArgs>(_listener_FileRequestReceived);
                    _listener.Start();
                }
                catch(Exception ex)
                {
                    MessageBox.Show("Can not start the DownloadListener: " + ex.Message, "Error", MessageBoxButton.OK);
                    Environment.Exit(-1);
                }
            }
        }

        private void _listener_FileRequestReceived(object sender, FileRequestEventArgs e)
        {
            try
            {
                e.DownloadClientHandler.SendFile("files\\" + e.Filename);
            }
            catch(Exception)
            {
                //wtf?
            }
        }

        private void _listener_ErrorOccured(object sender, ErrorArgs e)
        {
            MessageBox.Show("Error occured: " + e.Exception.Message, "Error", MessageBoxButton.OK);
            Environment.Exit(-1);
        }

        private void _listener_DownloadersChanged(object sender, DownloadersArgs e)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
            {
                CurrentActiveDownloads.Content = e.ActiveDownloads;
            }
            , null);            
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            try
            {
                if (_listener != null)
                    _listener.Stop();
            }
            catch (Exception)
            {
                //wtf
            }
            try
            {
                if (_client != null)
                    _client.StopDownload();
            }
            catch (Exception)
            {
                //wtf
            }

        }
    }
}
